#pragma once

#include "WorldObject.h"
#include "EnemyObject.h"
#include "AttackObject.h"
#include "MovingObject.h"
#include "PlayerObject.h"
#include "ZoneObject.h"
#include "WorldTypes.h"
#include "ObjectTypes.h"
#include "FXTypes.h"
#include "Defines.h"

#include <vector>
#include <map>
#include <queue>

#define NO_SEED 0
#define WANT_SERVERSEED 1

class WorldHandler
{
	private:
		std::vector<WorldObject*> worldObjects;
		std::vector<MovingObject*> movingObjects;
		std::vector<LivingObject*> livingObjects;
		std::vector<EnemyObject*> enemyObjects;
		std::vector<PlayerObject*> playerObjects;
		std::vector<AttackObject*> attackObjects;
		std::vector<ZoneObject*> zoneObjects;
		
		#if 0
		std::map<int, WorldObject> worldObjects;
		std::map<int, MovingObject> movingObjects;
		std::map<int, LivingObject> livingObjects;
		std::map<int, EnemyObject> enemyObjects;
		std::map<int, PlayerObject> playerObjects;
		std::map<int, AttackObject> attackObjects;
		std::map<int, ZoneObject> zoneObjects;
		#endif
	
		std::map<int, MovingObject*> movingIDMap;
		std::map<int, LivingObject*> livingIDMap;
		std::map<int, EnemyObject*> enemyIDMap;
		std::map<int, AttackObject*> attackIDMap;
		
		WorldObject* compassObject;
		
		scene::ITerrainSceneNode* randomTerrain;
		
		unsigned int localPlayerIndex;
		std::string localPlayerName;
		unsigned int playerCount;
		
		f32 frameDelta;

		unsigned int randomSeed;
		int highestID;
		ZoneObject* activeRandomZoneObject;
		
		unsigned int aliveEnemiesCount;
		unsigned int additionalEnemyCount;
		bool isCompassObjectActive;
	public:
		WorldHandler();
		~WorldHandler();
		
		void setFrameDelta(f32 passedDelta);
		f32 getFrameDelta();
		
		void addWorldObject(WorldObject* object, int ID = -1);
		void removeWorldObject(WorldObject* object);
		void addZoneObject(ZoneObject* object);
		
		std::vector<WorldObject*> getWorldObjects();
		std::vector<MovingObject*> getMovingObjects();
		std::vector<PlayerObject*> getPlayerObjects();
		std::vector<EnemyObject*> getEnemyObjects();
		std::vector<LivingObject*> getLivingObjects();
		std::vector<AttackObject*> getAttackObjects();

		std::map<int, LivingObject*> getLivingIDMap();
		std::map<int, MovingObject*> getMovingIDMap();
		std::map<int, EnemyObject*> getEnemyIDMap();
		std::map<int, AttackObject*> getAttackIDMap();
		
		WorldObject* getCompassObject();

		ZoneObject* getZoneObject(unsigned int index);
		ZoneObject* getRandomRandomZoneObject();

		unsigned int getWorldObjectsCount();
		unsigned int getMovingObjectsCount();
		unsigned int getPlayerObjectsCount();

		void setPlayerCount(unsigned int passedPlayerCount);
		void setLocalPlayerIndex(unsigned int passedLocalPlayerIndex);
		
		PlayerObject* setupNewPlayer(const std::string name, core::vector3df position);

		AttackObject* setupAttack(core::vector3df startPos, core::matrix4 passedMat, AttackType type, bool addToWorld, const std::string& originatingPlayer, int ID = -1);
		scene::IParticleSystemSceneNode* createParticleSystem(AttackType type, scene::ISceneNode* parentNode);
        
		void setupWorldLighting();
		
		
		void runAI();
		void moveObjects();
		void updateAnimation(MovingObject* movingObject);
		
		void setupNode(WorldObject* object, int nodeID);

		void dismantleRandomZone();
		
		unsigned int getPlayerCount();
		unsigned int getLocalPlayerIndex();
		
		unsigned int getAliveEnemiesCount();
		void decreaseAliveEnemiesCount();
		void setIsCompassObjectActive(bool passedIsActive);
		bool getIsCompassObjectActive();
		//int getHighestNodeID();

		void setupRandomZone();
		void setupTown();

		bool getAreAllPlayersDead();

		unsigned int getRandomSeed();
		void setRandomSeed(unsigned int seed);
		ZoneObject* getActiveRandomZoneObject();

		void setHighestID(const int passedHighestID);
		
		void setAdditionalEnemyCount(unsigned int passedCount);
	private:
		scene::ITerrainSceneNode* setupTerrain(const char* texture, f32 location);
};

extern WorldHandler globalWorldHandler;

//q
